/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/
#include <string.h>
#include <flgrCoreMalloc.h>
#include <flgrCoreDispatch.h>
#include "flgrRtView.h"

/*!
 * \defgroup group_fulguro_realtimetools_vdisp Video Display
 * \brief Video display management
 * \ingroup group_fulguro_realtimetools
 * @{
 */

////////////////////////////////////////////////////////////////////////////
/*! Create the window
 *  @param data : pointer to image to be used for setting size and type during window creation
 *  @param size_yfactor : an integer to define how many image to be displayed in vertical
 *  @param size_xfactor : an integer to define how many image to be displayed in horizontal
 *  @return pointer to a FLGR_RtView2D structure
 */
//////////////////////////////////////////////////////////////////
FLGR_RtView2D *flgr2d_rtview_create(FLGR_Data2D *data, int size_yfactor, int size_xfactor) {
  FLGR_RtView2D *screen;
  int bps;
  int i;

  FLGR_DECLARE_FUNCTION;

  if(data==NULL){
    POST_ERROR("Null objects!\n");
    return NULL;
  }

  if( SDL_Init( SDL_INIT_VIDEO ) == -1 ) {
    POST_ERROR("Could not init SDL:  %s\n", SDL_GetError( ) );
    return NULL;
  }

  bps = data->spp * data->bps;

  if((bps != 8) && (bps != 24) && (bps != 32)) {
    POST_ERROR("bps or spp invalid\n");
    return NULL;
  }

  screen = flgr_malloc(sizeof(FLGR_RtView2D));


  screen->size_xfactor = size_xfactor;
  screen->size_yfactor = size_yfactor;
  screen->bps = bps;

  atexit( SDL_Quit );
  screen->surface = SDL_SetVideoMode( data->size_x*size_xfactor, data->size_y*size_yfactor,
				      bps, SDL_HWSURFACE );
  SDL_WM_SetCaption("RtView", NULL );

  if(bps==8) {
    for(i=0;i<256;i++) {
      screen->palette[i].r=i;
      screen->palette[i].g=i;
      screen->palette[i].b=i;
    }
    SDL_SetPalette(screen->surface, SDL_LOGPAL|SDL_PHYSPAL, screen->palette, 0, 256);
  }else if(bps==24) {
    screen->surface->format->Rmask  = 0x000000FF;
    screen->surface->format->Gmask  = 0x0000FF00;
    screen->surface->format->Bmask  = 0x00FF0000;
    screen->surface->format->Amask  = 0xFF000000;
    screen->surface->format->Rshift = 0;
    screen->surface->format->Gshift = 8;
    screen->surface->format->Bshift = 16;
    screen->surface->format->Ashift = 24;
    screen->surface->format->Rloss = 0;
    screen->surface->format->Gloss = 0;
    screen->surface->format->Bloss = 0;
    screen->surface->format->Aloss = 0;
  }

  if( screen == NULL ) {
    POST_ERROR( "Can't set video mode: %s\n", SDL_GetError( ) );
    return NULL;
  }

  return screen;

}



////////////////////////////////////////////////////////////////////////////
/*! @brief refresh a part of the window with an image
 *  @param screen : pointer to the window structure
 *  @param data : pointer to image to be used for window refresh
 *  @param size_ypos : an integer to define vertical image position in the window
 *  @param size_xpos : an integer to define horizontal image position in the window
 *  @return FLGR_RET_OK, ...
 */
////////////////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_rtview_refresh(FLGR_RtView2D *screen, FLGR_Data2D *data, int size_ypos, int size_xpos) {
  int i;
  int Bps = data->spp * (data->bps>>3);
  int w = data->size_x;
  int h = data->size_y;
  int wfact = screen->size_xfactor;
  int hfact = screen->size_yfactor;
  void *psf = screen->surface->pixels + w*size_xpos*Bps + h*size_ypos*w*wfact*Bps;

  FLGR_DECLARE_FUNCTION;

  if((screen==NULL) || (data==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }


  if(size_xpos>=wfact) {
    POST_WARNING("Width position out of the screen window");
    size_xpos = screen->size_xfactor-1;
  }

  if(size_ypos>=hfact) {
    POST_WARNING("Height position out of the screen window");
    size_ypos = screen->size_yfactor-1;
  }

  if(SDL_MUSTLOCK(screen->surface)) {
    if(SDL_LockSurface( screen->surface )<0) {
      POST_ERROR("Could not Lock SDL surface\n");
      return FLGR_RET_UNDEFINED_ERROR;
    }
  }

  for(i=0;i<h;i++) {
    memcpy(psf, data->array[i], w*Bps);
    psf+=w*Bps*wfact;
  }

  if(SDL_MUSTLOCK(screen->surface)) {
    SDL_UnlockSurface( screen->surface );
  }

  if( SDL_Flip( screen->surface ) == -1 ) {
    POST_ERROR("Could not refresh SDL window\n");
    return FLGR_RET_UNDEFINED_ERROR;
  }
  SDL_UpdateRect(screen->surface, 0, 0, w, h);
  return FLGR_RET_OK;
}

////////////////////////////////////////////////////////////////////////////
/*! @brief destroy window
 *  @param screen : pointer to the window structure
 *  @return nothing
 */
////////////////////////////////////////////////////////////////////////////
void flgr2d_rtview_destroy(FLGR_RtView2D *screen) {
  FLGR_DECLARE_FUNCTION;

  SDL_FreeSurface(screen->surface);
  flgr_free(screen);
  SDL_Quit();
}


////////////////////////////////////////////////////////////////////////////
/*! @brief Apply the palette in the RtView structure on the window
 *  @param screen : pointer to the window structure
 *  @param rTable : integer array of size 256 for red color table
 *  @param gTable : integer array of size 256 for green color table
 *  @param bTable : integer array of size 256 for blue color table
 *  @return FLGR_RET_OK, ...
 */
////////////////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_rtview_set_palette(FLGR_RtView2D *screen, int *rTable, int *gTable, int *bTable) {
  int i;

  FLGR_DECLARE_FUNCTION;

  if(screen==NULL){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }


  if(screen->bps != 8)  {
    POST_ERROR("Pallete could only be used with 8 bits display!\n");
    return FLGR_RET_UNDEFINED_ERROR;
  }

  for(i=0 ; i<256 ; i++) {
    screen->palette[i].r = rTable[i];
    screen->palette[i].g = gTable[i];
    screen->palette[i].b = bTable[i];
  }


  SDL_SetPalette(screen->surface, SDL_LOGPAL|SDL_PHYSPAL, screen->palette, 0, 256);


  return FLGR_RET_OK;
}


//! @}
